package com.geline.easyexcel.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.geline.easyexcel.annotation.ExcelValid;
import com.geline.easyexcel.domain.ExcelError;
import com.geline.easyexcel.domain.RegexEnum;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * 数据检验
 *
 * @author: mengxin
 * @date: 2024/1/12 21:16
 */
@Slf4j
public class ExcelValidUtil {

    public static List<ExcelError> valid(int row, Object object) {
        List<ExcelError> list = new ArrayList<>();
        // 通过反射获取类的所有属性字段
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            //设置可访问
            field.setAccessible(true);
            // 进行判断 如果属性上有 @ExcelIgnore 注解或者没有 @ExcelProperty则表示该字段不参数映射, 跳过
            if (field.isAnnotationPresent(ExcelIgnore.class) || !field.isAnnotationPresent(ExcelProperty.class)) {
                continue;
            }

            //属性的值
            Object fieldValue = null;
            try {
                fieldValue = field.get(object);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("导入参数检查失败");
            }
            //是否包含自定义校验注解
            boolean hasValid = field.isAnnotationPresent(ExcelValid.class);
            if (hasValid) {
                ExcelProperty property = field.getAnnotation(ExcelProperty.class);
                int column = property.index();
                // 获取自定义注解
                ExcelValid annotation = field.getAnnotation(ExcelValid.class);
                // 非空校验
                boolean notNull = annotation.notNull(); // 获取注解notNull属性的值
                if (notNull && Objects.isNull(fieldValue)) {
                    log.warn(">>>>>>>>> find notNull [{} = {}]", field.getName(), fieldValue);
                    list.add(new ExcelError(row, column, annotation.validNotNullTip()));
                }
                // 非空校验
                boolean notBlank = annotation.notBlank(); // 获取注解notBlank属性的值
                if (notBlank) {
                    if(fieldValue==null || StrUtil.isBlank(String.valueOf(fieldValue))){
                        log.warn(">>>>>>>>> find notBlank [{} = {}]", field.getName(), fieldValue);
                        list.add(new ExcelError(row, column, annotation.validNotBlankTip()));
                    }
                }
                // 长度校验
                int length = annotation.length(); // 获取注解length属性的值
                if (length > 0 && String.valueOf(fieldValue).length()>length) {
                    log.warn(">>>>>>>>> find length [{} = {}]", field.getName(), fieldValue);
                    list.add(new ExcelError(row, column, String.format(annotation.validLengthTip(), length)));
                }
                // 正则校验
                RegexEnum regexEnum = annotation.regexEnum();
                String regex = annotation.regex();
                if(regexEnum!=null && regexEnum!=RegexEnum.no){
                    try{
                        regexEnum.getPattern().matcher(String.valueOf(fieldValue));
                    }catch (Exception e){
                        log.warn(">>>>>>>>> find RegexEnum [{} = {}], 不匹配：{}", field.getName(), fieldValue, regexEnum.getTitle());
                        String title = regexEnum.getTitle();
                        list.add(new ExcelError(row, column, String.format(annotation.validRegexTip(), title)));
                    }
                }else if(StrUtil.isNotBlank(regex)){
                    try{
                        Pattern.compile(regex).matcher(String.valueOf(fieldValue));
                    }catch (Exception e){
                        log.warn(">>>>>>>>> find regex [{} = {}], 不匹配：{}", field.getName(), fieldValue, regex);
                        list.add(new ExcelError(row, column, String.format(annotation.validRegexTip(), regex)));
                    }
                }
                // 类型校验
                CellDataTypeEnum type = annotation.type(); // 获取注解type属性的值
                if (!validType(type, fieldValue)) {
                    log.warn(">>>>>>>>> find validType [{} = {}]", field.getName(), fieldValue);
                    list.add(new ExcelError(row, column, String.format(annotation.validTypeTip(), type.name())));
                }
                // 当前月校验
                boolean curMonth = annotation.curMonth(); // 获取注解curMonth属性的值
                if (curMonth) {
                    String month = DateUtil.format(new Date(), "yyyy-MM");
                    if(!month.equals(String.valueOf(fieldValue))){
                        log.warn(">>>>>>>>> find curMonth [{} = {}]", field.getName(), fieldValue);
                        list.add(new ExcelError(row, column, annotation.validCurMonthTip()));
                    }
                }
            }
        }
        return list;
    }

    // 类型转换校验
    private static Boolean validType(CellDataTypeEnum type, Object fieldValue) {
        try {
            switch (type){
                case NUMBER: Double.valueOf(String.valueOf(fieldValue)); break;
                case STRING: String.valueOf(fieldValue); break;
                case BOOLEAN: Boolean.valueOf(String.valueOf(fieldValue)); break;
                default: break;
            }
        }catch (Exception e){
            // 转换失败返回false
            return false;
        }
        return true;
    }
}
